/* infutil.h -- types and macros common to blocks and codes
 * Copyright (C) 1995-2002 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* WARNING: this file should *not* be used by applications. It is
   part of the implementation of the compression library and is
   subject to change. Applications should only use zlib.h.
 */

#ifndef _INFUTIL_H
#define _INFUTIL_H

typedef enum
{
    TYPE,       /* get type bits (3, including end bit) */
    LENS,       /* get lengths for stored */
    STORED,     /* processing stored block */
    TABLE,      /* get table lengths */
    BTREE,      /* get bit lengths tree for a dynamic block */
    DTREE,      /* get length, distance trees for a dynamic block */
    CODES,      /* processing fixed or dynamic block */
    DRY,        /* output remaining window bytes */
    DONE,       /* finished last block, done */
    BAD
}               /* got a data error--stuck here */
inflate_block_mode;

/* inflate blocks semi-private state */
struct inflate_blocks_state
{

    /* mode */
    inflate_block_mode mode;    /* current inflate_block mode */

    /* mode dependent information */
    union
    {
        uInt left;      /* if STORED, bytes left to copy */
        struct
        {
            uInt table;         /* table lengths (14 bits) */
            uInt index;         /* index into blens (or border) */
            uIntf* blens;       /* bit lengths of codes */
            uInt bb;            /* bit length tree depth */
            inflate_huft* tb;   /* bit length decoding tree */
        } trees;        /* if DTREE, decoding info for trees */
        struct
        {
            inflate_codes_statef
            * codes;
        } decode;       /* if CODES, current state */
    } sub;              /* submode */
    uInt last;          /* true if this block is the last block */

    /* mode independent information */
    uInt bitk;          /* bits in bit buffer */
    uLong bitb;         /* bit buffer */
    inflate_huft* hufts; /* single malloc for tree space */
    Bytef* window;      /* sliding window */
    Bytef* end;         /* one byte after sliding window */
    Bytef* read;        /* window read pointer */
    Bytef* write;       /* window write pointer */
    check_func checkfn; /* check function */
    uLong check;        /* check on output */

};


/* defines for inflate input/output */
/*   update pointers and return */
#define UPDBITS { s->bitb = b; s->bitk = k; }
#define UPDIN { z->avail_in = n; z->total_in += p - z->next_in; z->next_in = p; }
#define UPDOUT { s->write = q; }
#define UPDATE { UPDBITS UPDIN UPDOUT }
#define LEAVE { UPDATE return inflate_flush(s, z, r); }
/*   get bytes and bits */
#define LOADIN { p = z->next_in; n = z->avail_in; b = s->bitb; k = s->bitk; }
#define NEEDBYTE { if (n) r = Z_OK;else LEAVE }
#define NEXTBYTE (n--, *p++)
#define NEEDBITS(j) { while (k < (j)) { NEEDBYTE; b |= ((uLong)NEXTBYTE) << k; k += 8; } }
#define DUMPBITS(j) { b >>= (j); k -= (j); }
/*   output bytes */
#define WAVAIL (uInt)(q < s->read ? s->read - q - 1 : s->end - q)
#define LOADOUT { q = s->write; m = (uInt)WAVAIL; }
#define WRAP { if (q == s->end && s->read != s->window) { q = s->window; m = (uInt)WAVAIL; } }
#define FLUSH { UPDOUT r = inflate_flush(s, z, r); LOADOUT }
#define NEEDOUT { if (m == 0) { WRAP if (m == 0) { FLUSH WRAP if (m == 0) LEAVE } } r = Z_OK;}
#define OUTBYTE(a) { *q++ = (Byte)(a); m--; }
/*   load local pointers */
#define LOAD { LOADIN LOADOUT }

/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
#ifndef NO_INFLATE_MASK
local uInt inflate_mask[17];
#endif

/* copy as much as possible from the sliding window to the output area */
local int inflate_flush OF((
                               inflate_blocks_statef *,
                               z_streamp,
                               int));

#endif